import 'dart:async';
import 'package:my_shop/timer/timer_task_config_manager.dart';
import 'package:my_shop/util/extension/list_extension.dart';
import 'package:my_shop/util/logs.dart';
import 'package:my_shop/timer/timer_task_id.dart';
import 'package:my_shop/timer/timer_task_config.dart';
import 'package:flutter/material.dart';
import 'package:sp_util/sp_util.dart';

/// 定时任务服务
class TimerService {
  static final TimerService _instance = TimerService._internal();
  final Map<TimerTaskId, Timer> _timers = {};
  final Map<TimerTaskId, TimerTaskConfig> _taskConfigs = {};

  // 缓存key前缀
  static const String _lastExecuteTimePrefix = 'timer_last_execute_';
  static const String _dynamicTaskConfigPrefix = 'timer_dynamic_config_';

  factory TimerService() => _instance;

  TimerService._internal();

  /// 初始化所有定时任务
  void initAllTasks() {
    // 初始化固定任务
    final configs = TimerTaskConfigManager().getAllTaskConfigs();
    for (final config in configs) {
      registerTask(config);
    }

    // 初始化动态任务
    _initDynamicTasks();
  }

  /// 初始化动态任务
  void _initDynamicTasks() {
    // 从本地存储中恢复动态任务配置
    final dynamicTaskIds =
        SpUtil.getStringList('${_dynamicTaskConfigPrefix}ids') ?? [];
    for (final taskIdStr in dynamicTaskIds) {
      final taskId = TimerTaskId.values.firstWhereOrNull(
        (id) => id.id == taskIdStr,
      );
      if (taskId != null) {
        final configJson =
            SpUtil.getString('${_dynamicTaskConfigPrefix}${taskId.id}');
        if (configJson != null) {
          try {
            final config = TimerTaskConfig.fromJson(configJson);
            registerTask(config);
          } catch (e) {
            printLog('恢复动态任务失败: $taskId');
          }
        }
      }
    }
  }

  /// 注册定时任务
  void registerTask(TimerTaskConfig config) {
    // 如果已存在相同ID的任务，先取消它
    cancelTask(config.taskId);

    _taskConfigs[config.taskId] = config;
    _scheduleTask(config);

    // 如果是动态任务，保存配置到本地存储
    if (_isDynamicTask(config.taskId)) {
      _saveDynamicTaskConfig(config);
    }
  }

  /// 判断是否是动态任务
  bool _isDynamicTask(TimerTaskId taskId) {
    // 检查任务是否在固定任务列表中
    final fixedConfigs = TimerTaskConfigManager().getAllTaskConfigs();
    return !fixedConfigs.any((config) => config.taskId == taskId);
  }

  /// 保存动态任务配置
  void _saveDynamicTaskConfig(TimerTaskConfig config) {
    try {
      // 保存任务ID列表
      List<String> dynamicTaskIds = List.from(
          SpUtil.getStringList('${_dynamicTaskConfigPrefix}ids') ?? []);
      if (!dynamicTaskIds.contains(config.taskId.id)) {
        dynamicTaskIds.add(config.taskId.id);
        SpUtil.putStringList('${_dynamicTaskConfigPrefix}ids', dynamicTaskIds);
      }

      // 保存任务配置
      SpUtil.putString(
          '${_dynamicTaskConfigPrefix}${config.taskId.id}', config.toJson());
    } catch (e) {
      printLog('保存动态任务配置失败: ${config.taskId}');
    }
  }

  /// 清除动态任务
  void clearDynamicTasks() {
    final dynamicTaskIds =
        SpUtil.getStringList('${_dynamicTaskConfigPrefix}ids') ?? [];
    for (final taskIdStr in dynamicTaskIds) {
      final taskId = TimerTaskId.values.firstWhereOrNull(
        (id) => id.id == taskIdStr,
      );
      if (taskId != null) {
        cancelTask(taskId);
        SpUtil.remove('${_dynamicTaskConfigPrefix}${taskId.id}');
      }
    }
    SpUtil.remove('${_dynamicTaskConfigPrefix}ids');
  }

  /// 更新定时任务的执行间隔
  /// 用于动态更新任务执行时间，比如token刷新
  void updateTaskInterval(TimerTaskId taskId, Duration newInterval) {
    final config = _taskConfigs[taskId];
    if (config == null) {
      printLog('更新定时任务失败：任务不存在 $taskId');
      return;
    }

    // 创建新的配置
    final newConfig = TimerTaskConfig(
      taskId: config.taskId,
      interval: newInterval,
      callback: config.callback,
      executeImmediately: false,
      executeOnInitIfExpired: config.executeOnInitIfExpired,
    );

    // 重新注册任务
    registerTask(newConfig);
    printLog('已更新定时任务 $taskId 的执行间隔为 ${newInterval.inSeconds}秒');
  }

  /// 更新定时任务的回调函数
  void updateTaskCallback(TimerTaskId taskId, VoidCallback newCallback) {
    final config = _taskConfigs[taskId];
    if (config == null) {
      printLog('更新定时任务回调失败：任务不存在 $taskId');
      return;
    }

    // 创建新的配置
    final newConfig = TimerTaskConfig(
      taskId: config.taskId,
      interval: config.interval,
      specificTime: config.specificTime,
      callback: newCallback,
      executeImmediately: false,
      executeOnInitIfExpired: config.executeOnInitIfExpired,
    );

    // 重新注册任务
    registerTask(newConfig);
    printLog('已更新定时任务 $taskId 的回调函数');
  }

  /// 更新定时任务的执行时间
  void updateTaskSpecificTime(TimerTaskId taskId, TimeOfDay newTime) {
    final config = _taskConfigs[taskId];
    if (config == null) {
      printLog('更新定时任务失败：任务不存在 $taskId');
      return;
    }

    // 创建新的配置
    final newConfig = TimerTaskConfig(
      taskId: config.taskId,
      specificTime: newTime,
      callback: config.callback,
      executeImmediately: false,
      executeOnInitIfExpired: config.executeOnInitIfExpired,
    );

    // 重新注册任务
    registerTask(newConfig);
    printLog('已更新定时任务 $taskId 的执行时间为 ${newTime.hour}:${newTime.minute}');
  }

  /// 调度任务
  void _scheduleTask(TimerTaskConfig config) {
    if (config.interval != null) {
      _scheduleIntervalTask(config);
    } else if (config.specificTime != null) {
      _scheduleSpecificTimeTask(config);
    }
  }

  /// 调度间隔任务
  void _scheduleIntervalTask(TimerTaskConfig config) {
    final lastExecuteTime = _getLastExecuteTime(config.taskId);
    final now = DateTime.now();

    // 检查是否需要立即执行
    bool shouldExecuteNow = false;

    if (config.executeImmediately ?? false) {
      shouldExecuteNow = true;
    } else if ((config.executeOnInitIfExpired ?? false) &&
        lastExecuteTime != null) {
      final timeSinceLastExecute = now.difference(lastExecuteTime);
      if (timeSinceLastExecute >= config.interval!) {
        shouldExecuteNow = true;
      }
    }

    if (shouldExecuteNow) {
      _executeTask(config);
    }

    // 计算下次执行时间
    DateTime nextExecuteTime;
    if (lastExecuteTime == null) {
      nextExecuteTime = now.add(config.interval!);
    } else {
      final periods = (now.difference(lastExecuteTime).inMilliseconds /
                  config.interval!.inMilliseconds)
              .floor() +
          1;
      nextExecuteTime = lastExecuteTime.add(config.interval! * periods);
    }

    // 计算首次执行延迟
    final initialDelay = nextExecuteTime.difference(now);

    // 创建定时器
    final timer = Timer(initialDelay, () {
      _executeTask(config);
      // 创建周期性定时器
      _timers[config.taskId] = Timer.periodic(config.interval!, (timer) {
        _executeTask(config);
      });
    });

    _timers[config.taskId] = timer;
  }

  /// 调度每日固定时间任务
  void _scheduleSpecificTimeTask(TimerTaskConfig config) {
    final now = DateTime.now();
    final targetTime = DateTime(
      now.year,
      now.month,
      now.day,
      config.specificTime!.hour,
      config.specificTime!.minute,
    );

    // 计算首次执行延迟
    Duration initialDelay;
    if (now.isAfter(targetTime)) {
      // 如果当前时间已经过了目标时间，设置为明天
      initialDelay = targetTime.add(const Duration(days: 1)).difference(now);
    } else {
      initialDelay = targetTime.difference(now);
    }

    // 检查是否需要立即执行
    if ((config.executeImmediately ?? false) ||
        ((config.executeOnInitIfExpired ?? false) && now.isAfter(targetTime))) {
      _executeTask(config);
    }

    // 创建定时器
    final timer = Timer(initialDelay, () {
      _executeTask(config);
      // 重新调度下一天的任务
      _scheduleSpecificTimeTask(config);
    });

    _timers[config.taskId] = timer;
  }

  /// 执行任务
  void _executeTask(TimerTaskConfig config) {
    try {
      config.callback();
      _updateLastExecuteTime(config.taskId);
    } catch (e) {
      printLog('定时任务执行失败: ${config.taskId}');
    }
  }

  /// 获取上次执行时间
  DateTime? _getLastExecuteTime(TimerTaskId taskId) {
    final timestamp = SpUtil.getInt('$_lastExecuteTimePrefix${taskId.id}');
    return timestamp != null
        ? DateTime.fromMillisecondsSinceEpoch(timestamp)
        : null;
  }

  /// 更新上次执行时间
  void _updateLastExecuteTime(TimerTaskId taskId) {
    SpUtil.putInt('$_lastExecuteTimePrefix${taskId.id}',
        DateTime.now().millisecondsSinceEpoch);
  }

  /// 取消定时任务
  void cancelTask(TimerTaskId taskId) {
    final timer = _timers[taskId];
    if (timer != null) {
      timer.cancel();
      _timers.remove(taskId);
      _taskConfigs.remove(taskId);
    }
  }

  /// 取消所有定时任务
  void cancelAllTasks() {
    for (var timer in _timers.values) {
      timer.cancel();
    }
    _timers.clear();
    _taskConfigs.clear();
  }

  /// 检查任务是否存在
  bool hasTask(TimerTaskId taskId) {
    return _timers.containsKey(taskId);
  }

  /// 获取所有正在运行的任务ID
  List<TimerTaskId> getRunningTaskIds() {
    return _timers.keys.toList();
  }

  /// 获取任务配置
  TimerTaskConfig? getTaskConfig(TimerTaskId taskId) {
    return _taskConfigs[taskId];
  }

  /// 获取所有任务配置
  List<TimerTaskConfig> getAllTaskConfigs() {
    return _taskConfigs.values.toList();
  }
}
